// 8085Object.h: interface for the C8085Object class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_8085OBJECT_H__E571CEB8_7AAF_11D2_8064_00A0C91F41A7__INCLUDED_)
#define AFX_8085OBJECT_H__E571CEB8_7AAF_11D2_8064_00A0C91F41A7__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "MyTypedef.h"
#include "InstructionSet.h"
#include "constants.h"
#include "DebugData.h"

#if defined(_MSC_VER)
#define GUI_AVAILABLE 1
#endif

#define     SIGN                128
#define     ZERO                64
#define     AUXCARRY            16
#define     PARITY              4
#define     CARRY               1

const word MEM_SIZE = 0xffff;   // 64K of Memory
#define SEGMENTS    1024

class C8085Object  : public CInstructionSet
{
public:
    C8085Object();
    virtual ~C8085Object();

    //Implementation
public:
	typedef struct tagInstructionArray
	{
		runTimeFunction r;
		displayFunction d;
	}InstructionArray;


	// the various 8085 flags, these exactly correspond to the way
	// flags are stored in the actual microprocessor
	typedef struct tagPSW
	{
		// the flags can be manipulated by either changing the values
		// in the structure 'bits' or by the integer 'wholeFlags'
		// The purpose of the 'wholeFlags' is for easier push and pop
		// operations which are used when the 'push psw' instruction is 
		// executed.  'wholeFlags' should never be used to set the
		// individual flags.
		union 
		{
			struct 
			{
				unsigned char
					carry   :1,
							:1, 
					parity  :1,
							:1,
					auxCarry:1,
							:1,
					zero    :1,
					sign    :1;
			}bits;
			byte wholeFlags;
		}flags;
	}PSW;

// interface
public:
	inline int NumTo7Segment(int x);
	BOOL IsLedDataModified();
	void SetLedDataModified(BOOL bModified=TRUE);
	void DoIntelSDKCalls();
	int  BadSystemCall();
	int  PerformSystemCall();
	///////////////////////////////////////////////
    // System functions
    void _SystemBlankDisplay();
	void _SystemReset();
	void _SystemDisplayDot();
	void _SystemDisplayData();
    void _SystemDisplayErr();
    void _SystemReadFromKeyboard();
    void _SystemCodeConversion();
    void _SystemLengthOfBlock();
    void _SystemGenerateTone();
    void _SystemDelay();
    void _SystemDisplayHLData();
    void _SystemGetDataFromKeyboard();
    void _SystemDisplayDataUsingMemoryPointer();
    void _SystemSerialInput();
    void _SystemSerialOutput();
    void _SystemPrintData();
    void _SystemPrintCRLF();


    ///////////////////////////////////////////////
    void SetExceptionOnRet(BOOL bFlag);

    ///////////////////////////////////////////////
    //functions to maniupuate LEDS
    void BlankAllLeds();
	void SetStatusLed(int nLed,int nData);
	void SetDataLed(int nLed,int nData);
	void SetAddressLed(int nLed,int nData);
	void SetLedData(int nIndex,int nData);
	int  GetLedData(int nIndex);
    //////////////////////////////////////////////

    inline  byte GetBreakPtOpCode();
    virtual CString GetErrorPrefix();
    
    // the following four functions convert the data at the mem[addr] into string
    char * DisplayWord(word addr,char *szPrefix);
    char * DisplayByte(word addr,char *szPrefix);

    // These functions help segment the memory into various segments\
    // which are very helpful in fast display of instructions in the
    // instruction window independent of the memory location.
    word GetMemSize();
    void AdjustSegment(word addr);
    word GetEndAddrInSegment(unsigned segment);
    int WhichSegment(word addr);
    inline int GetInstrPerSeg();
    void RefreshSegments(int startSegment=1,int numberOfSegment=SEGMENTS);
    
    // used for display and internal operations
    char * OpcodeToString(word addr,char *szPrefix="");
    inline void InternalPush(word w=0);
    void SetFlagsAfterLogicalInstruction();
    void SetFlagsAfterLogicalInstruction(byte b);
    void StartMachine();
    void SimulateOneInstruction();
    void ResetMachine();

    // inline functions
    inline byte ReadPort(byte addr)     { return m_Ports[addr]; }
    inline void WritePort(byte addr,byte data)     { m_Ports[addr] = data; }
    inline int GetSegmentSize() { return SEGMENTS; }
    inline int GetInstructionLenAt(word addr) 
    { 
        return GetInstructionLen(ReadMemByte(addr));
    }

    // get the number of times 'call' instruction was executed without a matching
    // 'ret' instruction
    inline int GetStackDepth()          { return m_nCallStackDepth; }
    inline void IncrementStackDepth()    { m_nCallStackDepth++;  }
    inline void DecrementStackDepth()    { m_nCallStackDepth--;  }

    void SetStartIP(word ip);
    void Init();
    void InsertMachineCode(word addr,byte);
    void InsertMachineCode(word addr,byte opCode,word operand);
    void InsertMachineCode(word addr,byte opCode, byte operand);

    // Functions to manipulate the memory
    inline byte ReadMemByte(word address) { return mem[address]; }
    inline word ReadMemWord(word address) 
    { 
        return (mem[address+1]<<8)+mem[address];
    }
    inline void WriteMem(word address,byte data) 
    { 
        mem[address] = data;
        m_LastWriteAddress = address;
    }
    inline void WriteMem(word address,word data) 
    { 
        mem[address] = data&0xff;  
        mem[address+1] = data>>8;
        m_LastWriteAddress = address;
    }
    inline word &GetIP()     { return m_ip; }
    inline byte &GetA()      { return m_A;}
    inline byte &GetB()      { return m_B;}
    inline byte &GetC()      { return m_C;}
    inline byte &GetD()      { return m_D;}
    inline byte &GetE()      { return m_E;}
    inline byte &GetH()      { return m_H;}
    inline byte &GetL()      { return m_L;}
    inline byte GetM()       { return mem[GetHL()];} /* equivalent to ReadMem */
    inline byte GetPSW()     { return m_PSW.flags.wholeFlags; }
    inline word &GetSP()     { return m_SP;}
    inline word GetBC()      { return (m_B<<8)+m_C ; }
    inline word GetDE()      { return (m_D<<8)+m_E ; }
    inline word GetHL()      { return (m_H<<8)+m_L ; }

    inline void SetSign(byte b)     
    { 
      //m_PSW = b ? (m_PSW | SIGN) : (m_PSW &= ~SIGN) ;   
        m_PSW.flags.bits.sign=b;
    }
    inline void SetZero(byte b)     
    { 
      //m_PSW = b ? (m_PSW | ZERO) : (m_PSW &= ~ZERO) ;   
        m_PSW.flags.bits.zero=b;
    }
    inline void SetParity(byte b)   
    {  
        //m_PSW = b ? (m_PSW | PARITY) : (m_PSW &= ~PARITY); 
        m_PSW.flags.bits.parity=b;
    }
    inline void SetAuxCarry(byte b) 
    {  
        //m_PSW = b ? (m_PSW | AUXCARRY) : (m_PSW &= ~AUXCARRY); 
        m_PSW.flags.bits.auxCarry=b;
    }
    inline void SetCarry(byte b)    
    {  
        //m_PSW = b ? (m_PSW | CARRY) : (m_PSW &= ~CARRY); 
        m_PSW.flags.bits.carry=b;
    }

    inline byte GetSign()           
    { 
        //return (m_PSW & SIGN)>>7;
        // the !! will autumatically convert the value of m_PSW.flags.bits.sign to
        // 0 or 1
        return !!m_PSW.flags.bits.sign;
    }
    inline byte GetZero()           
    { 
        //return (m_PSW & ZERO)>>6;      
        return !!m_PSW.flags.bits.zero;
    }
    inline byte GetParity()         
    { 
        //return (m_PSW & PARITY)>>2;    
        return !!m_PSW.flags.bits.parity;
    }
    inline byte GetAuxCarry()       
    { 
        //return (m_PSW & AUXCARRY)>>4;  
        return !!m_PSW.flags.bits.auxCarry;

    }
    inline byte GetCarry()          
    { 
        //return (m_PSW & CARRY);     
        return !!m_PSW.flags.bits.carry;
    }
    void SetParityFlag(byte data);



    inline void SetA(byte b)      {  m_A    = b;}
    inline void SetB(byte b)      {  m_B    = b;}
    inline void SetC(byte b)      {  m_C    = b;}
    inline void SetD(byte b)      {  m_D    = b;}
    inline void SetE(byte b)      {  m_E    = b;}
    inline void SetH(byte b)      {  m_H    = b;}
    inline void SetL(byte b)      {  m_L    = b;}
    inline void SetM(byte b)      { mem[GetHL()]=b;} /* equivalent to WriteMem */
    inline void SetPSW(byte b)    { m_PSW.flags.wholeFlags = b; }
    inline void SetSP(word w)     { m_SP   = w;}
    inline void SetBC(word w)     { SetB(w>>8);SetC(w&0xff); }
    inline void SetDE(word w)     { SetD(w>>8);SetE(w&0xff); }
    inline void SetHL(word w)     { SetH(w>>8);SetL(w&0xff); }

    inline void SetIP(word addr) { m_ip = addr; }
    byte InternalAdd(byte regData,byte data,BOOL bSetCarry=TRUE);

    inline void SetPtr(word addr) { m_Ptr = addr; }
    inline word GetPtr()          { return m_Ptr; }

    // data members
protected:
    byte mem[MEM_SIZE]; // 64 K of memory
    word m_ip;
    word m_StartIP;
    // registers
    byte m_A,m_B,m_C,m_D,m_E,m_H,m_L;
    PSW  m_PSW;
    //byte m_Sign,m_Carry,m_Zero,m_AuxCarry,m_Parity;
    word temp;
    word m_SP;
    byte m_Ports[256];
    word m_aSegments[SEGMENTS+1];
    byte m_Opcode;  // opcode the current instruction
    int  m_nInstructionsPerSegment;
    word m_LastWriteAddress;    // memory address of last write on to the memory
    char m_szTemporary[256];
    word m_Ptr;                 // used to insert instructions into memory while parsing
    // data displayed by the LEDS
    int  m_aLedData[NUM_OF_LEDS];
	// set to true if any system calls modifying the LED display are called
	BOOL m_bLedDataModified;	

    // number of times a call has been executed without a matching 'ret' instruction
    int  m_nCallStackDepth; 
	int  m_nSaveCallStackDepth;		// used for step out

    // generate exception after executing a 'ret' instruction, 
    // used to implement StepOut.
    BOOL m_bExceptionOnRet;  
    BOOL m_bGenDebugInfo;
    //CDebugData m_cDebugData;    // contains debug info

    static InstructionArray m_aInstructions[];

    // functions which do the simulation
    int  VKNop ();
    int  VKLxi ();
    int  VKStax();
    int  VKInx ();
    int  VKInr ();
    int  VKDcr ();
    int  VKMvi ();
    int  VKRlc ();
    int  VKInvalid();
    int  VKDad ();
    int  VKLdax();
    int  VKDcx ();
    int  VKRrc ();
    int  VKRal ();
    int  VKRar ();
    int  VKRim ();
    int  VKShld();
    int  VKDaa ();
    int  VKLhld();
    int  VKCma ();
    int  VKSim ();
    int  VKSta ();
    int  VKStc ();
    int  VKLda ();
    int  VKCmc ();
    int  VKMov ();
    int  VKHlt ();
    int  VKAdd ();
    int  VKAdc ();
    int  VKSub ();
    int  VKSbb ();
    int  VKAna ();
    int  VKXra ();
    int  VKOra ();
    int  VKCmp ();
    int  VKRnz ();
    int  VKPop ();
    int  VKJnz ();
    int  VKJmp ();
    int  VKCnz ();
    int  VKPush();
    int  VKAdi ();
    int  VKRst ();
    int  VKRz  ();
    int  VKRet ();
    int  VKJz  ();
    int  VKCz  ();
    int  VKCall();
    int  VKAci ();
    int  VKRnc ();
    int  VKJnc ();
    int  VKOut ();
    int  VKCnc ();
    int  VKSui ();
    int  VKRc  ();
    int  VKJc  ();
    int  VKIn  ();
    int  VKCc  ();
    int  VKSbi ();
    int  VKRpo ();
    int  VKJpo ();
    int  VKXthl();
    int  VKCpo ();
    int  VKAni ();
    int  VKRpe ();
    int  VKPchl();
    int  VKJpe ();
    int  VKXchg();
    int  VKCpe ();
    int  VKXri ();
    int  VKRp  ();
    int  VKJp  ();
    int  VKDi  ();
    int  VKCp  ();
    int  VKOri ();
    int  VKRm  ();
    int  VKSphl();
    int  VKJm  ();
    int  VKEi  ();
    int  VKCm  ();
    int  VKCpi ();
    int  VKBreakPoint();
};


///////////////////////////////////////////////////////////////
// inline functions go here
// the runtime opcode that is mapped to VKBreakPoint 
inline byte C8085Object::GetBreakPtOpCode()
{
    return 8;
}

#endif // !defined(AFX_8085OBJECT_H__E571CEB8_7AAF_11D2_8064_00A0C91F41A7__INCLUDED_)

